package com.ld.shieldsb.common.core.util.notice.wechat.application.tmplcard;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.PropertyNamingStrategy;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.ld.shieldsb.common.core.model.Result;
import com.ld.shieldsb.common.core.reflect.ModelUtil;
import com.ld.shieldsb.common.core.util.JsoupUtil;
import com.ld.shieldsb.common.core.util.ResultUtil;
import com.ld.shieldsb.common.core.util.StringUtils;
import com.ld.shieldsb.common.core.util.notice.wechat.EweChatTool;
import com.ld.shieldsb.common.core.util.notice.wechat.Type;
import com.ld.shieldsb.common.core.util.notice.wechat.application.EweChatApplicationParams;
import com.ld.shieldsb.common.core.util.notice.wechat.application.EwechatBasicMsgSender;
import com.ld.shieldsb.common.core.util.notice.wechat.application.EwechatResponse;
import com.ld.shieldsb.common.core.util.notice.wechat.application.tmplcard.button.TemplateCardButtonModel;
import com.ld.shieldsb.common.core.util.notice.wechat.application.tmplcard.button.TmplCardBtn;
import com.ld.shieldsb.common.core.util.notice.wechat.application.tmplcard.news.TemplateCardNewsModel;
import com.ld.shieldsb.common.core.util.notice.wechat.application.tmplcard.news.TmplCardImageModel;
import com.ld.shieldsb.common.core.util.notice.wechat.application.tmplcard.text.TemplateCardTextModel;
import com.ld.shieldsb.common.core.util.notice.wechat.log.EweChatLogFactory;
import com.ld.shieldsb.common.core.util.notice.wechat.log.EweChatLogModel;

/**
 * 模块卡片消息发送器
 * 
 * @ClassName TemplateCardMsgSender
 * @author <a href="mailto:donggongai@126.com" target="_blank">吕凯</a>
 * @date 2021年9月14日 上午10:29:02
 *
 */
public class TemplateCardMsgSender extends EwechatBasicMsgSender {

    /**
     * 
     * 转换任务卡片格式dataMap<br>
     * <br>
     * 
     * 投票选择型和多项选择型卡片仅企业微信3.1.12及以上版本支持 <br>
     * 文本通知型、图文展示型和按钮交互型三种卡片仅企业微信3.1.6及以上版本支持（但附件下载功能仍需更新至3.1.12）<br>
     * 
     * 特殊说明<br>
     * 
     * 仅有 按钮交互型、投票选择型、多项选择型 三种类型的卡片支持回调更新或通过接口更新卡片。 按钮交互型、投票选择型、多项选择型 三种类型的卡片可支持用户点击触发交互事件，需要开发者设置的回调接口来处理回调事件，回调协议可见文档 模板卡片事件推送，注意
     * 没有配置回调接口的应用不可发送这三种卡片。 开发者的服务收到回调事件后，需要根据协议返回相应的数据以更新卡片，对应的协议见文档 更新模版卡片消息。
     * 此接口发送这三种卡片消息之后，返回的参数里会带上response_code，可使用response_code调用更新模版卡片消息接口，response_code 24小时内有效，且只能调用一次接口。
     * 
     * @Title parse2TemplateCardDataMap
     * @author 吕凯
     * @date 2021年4月20日 上午9:14:45
     * @param agentid
     * @param sendTo
     * @param taskId
     * @param title
     * @param description
     * @param url
     * @param btns
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Map<String,Object>
     */

    public static Map<String, Object> parse2TemplateCardDataMap(String agentid, String sendTo, TemplateCardBasicModel model,
            Integer duplicateCheckInterval) {

        Map<String, Object> dataMap = defaultDataMap(agentid, sendTo, duplicateCheckInterval);

        dataMap.put(EweChatTool.MSG_TYPE, Type.TEMPLATE_CARD.value);

        SerializeConfig sconfig = new SerializeConfig();
        sconfig.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
        Map<String, Object> modelMap = JSONObject.parseObject(JSONObject.toJSONString(model, sconfig));
        log.warn("{}", modelMap);

        dataMap.put(Type.TEMPLATE_CARD.value, modelMap);
//        System.out.println(JSONObject.toJSONString(dataMap));
        return dataMap;
    }

    @SuppressWarnings("rawtypes")
    public static Result sendTemplateCardMsg(String corpid, String corpsecret, String agentid, String sendTo, TemplateCardBasicModel model,
            Integer duplicateCheckInterval) {
        if (model == null) {
            return ResultUtil.error("TemplateCardModel为空！");
        }
        if (StringUtils.isBlank(model.getCardType())) {
            return ResultUtil.error("cardType不能为空！");
        }

        if (ModelUtil.hasField(model, "cardAction") && ModelUtil.getModelValue(model, "cardAction") == null) {
            return ResultUtil.error("cardAction不能为空！");
        }
        // 含有此属性，并且不为空，并且条目大于3
        if (ModelUtil.hasField(model, "jumpList") && ModelUtil.getModelValue(model, "jumpList") != null
                && ((List) ModelUtil.getModelValue(model, "jumpList")).size() > 3) {
            return ResultUtil.error("jumpList最多3个！");
        }
        // 含有此属性，并且不为空，并且条目大于4
        if (ModelUtil.hasField(model, "verticalContentList") && ModelUtil.getModelValue(model, "verticalContentList") != null
                && ((List) ModelUtil.getModelValue(model, "verticalContentList")).size() > 4) {
            return ResultUtil.error("verticalContentList最多6个！");
        }
        // 含有此属性，并且不为空，并且条目大于6
        if (ModelUtil.hasField(model, "horizontalContentList") && ModelUtil.getModelValue(model, "horizontalContentList") != null
                && ((List) ModelUtil.getModelValue(model, "horizontalContentList")).size() > 6) {
            return ResultUtil.error("horizontalContentList最多6个！");
        }
        // 图文通知的图片
        if (ModelUtil.hasField(model, "cardImage") && ModelUtil.getModelValue(model, "cardImage") == null) {
            return ResultUtil.error("cardImage不能为空！");
        }
        // 按钮交互型的按钮

        if (ModelUtil.hasField(model, "buttonList") && ModelUtil.getModelValue(model, "buttonList") != null
                && ((List) ModelUtil.getModelValue(model, "buttonList")).size() > 6) {
            return ResultUtil.error("buttonList最多6个！");
        }

        return sendMsg(corpid, corpsecret, agentid, parse2TemplateCardDataMap(agentid, sendTo, model, duplicateCheckInterval));

    }

    /**
     * 发送文本类型的通知
     * 
     * @Title sendTemplateCardTextMsg
     * @author 吕凯
     * @date 2021年9月13日 上午9:48:33
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     * @param model
     * @param duplicateCheckInterval
     * @return Result
     */
    /*{
    "touser" : "UserID1|UserID2|UserID3",
    "toparty" : "PartyID1 | PartyID2",
    "totag" : "TagID1 | TagID2",
    "msgtype" : "template_card",
    "agentid" : 1,
    "template_card" : {
        "card_type" : "text_notice",
        "source" : {
            "icon_url": "图片的url",
            "desc": "企业微信"
        },
        "main_title" : {
            "title" : "欢迎使用企业微信",
            "desc" : "您的好友正在邀请您加入企业微信"
        },
        "emphasis_content": {
            "title": "100",
            "desc": "核心数据"
        },
        "sub_title_text" : "下载企业微信还能抢红包！",
        "horizontal_content_list" : [
            {
                "keyname": "邀请人",
                "value": "张三"
            },
            {
                "type": 1,
                "keyname": "企业微信官网",
                "value": "点击访问",
                "url": "https://work.weixin.qq.com"
            },
            {
                "type": 2,
                "keyname": "企业微信下载",
                "value": "企业微信.apk",
                "media_id": "文件的media_id"
            }
        ],
        "jump_list" : [
            {
                "type": 1,
                "title": "企业微信官网",
                "url": "https://work.weixin.qq.com"
            },
            {
                "type": 2,
                "title": "跳转小程序",
                "appid": "小程序的appid",
                "pagepath": "/index.html"
            }
        ],
        "card_action": {
            "type": 2,
            "url": "https://work.weixin.qq.com",
            "appid": "小程序的appid",
            "pagepath": "/index.html"
        }
    },
    "enable_id_trans": 0,
    "enable_duplicate_check": 0,
    "duplicate_check_interval": 1800
    }*/
    public static Result sendTemplateCardTextMsg(String corpid, String corpsecret, String agentid, String sendTo,
            TemplateCardTextModel model, Integer duplicateCheckInterval) {
        if (model != null) {
            model.setCardType(EweChatTool.TEMPL_CARD_TYPE_TEXT);
        }
        return sendTemplateCardMsg(corpid, corpsecret, agentid, sendTo, model, duplicateCheckInterval);

    }

    public static Result sendTemplateCardTextMsg(String sendTo, TemplateCardTextModel model, Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTemplateCardTextMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, model,
                duplicateCheckInterval);

    }

    /**
     * 发送文本类型的通知模板
     * 
     * @Title sendTemplateCardTextMsg
     * @author 吕凯
     * @date 2021年9月13日 上午9:43:56
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     * @param title
     *            一级标题，建议不超过36个字
     * @param description
     *            二级普通文本，建议不超过160个字
     * @param url，点击后跳转链接
     * @param duplicateCheckInterval
     * @return Result
     */
    public static Result sendTemplateCardTextMsg(String corpid, String corpsecret, String agentid, String sendTo, String title,
            String description, String url, Integer duplicateCheckInterval) {
        TemplateCardTextModel model = TemplateCardTextModel.builder().cardType(EweChatTool.TEMPL_CARD_TYPE_TEXT)
                .mainTitle(TmplCardMainTitleModel.builder().title(title).build()).subTitleText(description)
                .cardAction(TmplCardActionModel.builder().type(1).url(url).build()).build();
        return sendMsg(corpid, corpsecret, agentid, parse2TemplateCardDataMap(agentid, sendTo, model, duplicateCheckInterval));

    }

    public static Result sendTemplateCardTextMsg(String corpid, String corpsecret, String agentid, String sendTo, String title,
            String description, String url) {
        return sendTemplateCardTextMsg(corpid, corpsecret, agentid, sendTo, title, description, url, null);

    }

    /**
     * 
     * 发送模板任务卡片消息
     * 
     * @Title sendTaskCardMsg
     * @author 吕凯
     * @date 2021年4月20日 下午6:04:09
     * @param sendTo
     * @param taskId
     * @param title
     * @param description
     * @param url
     * @param btns
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Result
     */
    public static Result sendTemplateCardTextMsg(String sendTo, String title, String description, String url,
            Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTemplateCardTextMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, title, description, url,
                duplicateCheckInterval);
    }

    public static Result sendTemplateCardTextMsg(String sendTo, String title, String description, String url) {
        return sendTemplateCardTextMsg(sendTo, title, description, url, null);
    }

    // ========================================== 模板卡片：：图文展示型 ====================================
    /**
     * 发送图文展示型的通知
     * 
     * @Title sendTemplateCardNewsMsg
     * @author 吕凯
     * @date 2021年9月13日 上午9:48:33
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     * @param model
     * @param duplicateCheckInterval
     * @return Result
     */

    public static Result sendTemplateCardNewsMsg(String corpid, String corpsecret, String agentid, String sendTo,
            TemplateCardNewsModel model, Integer duplicateCheckInterval) {
        if (model != null) {
            model.setCardType(EweChatTool.TEMPL_CARD_TYPE_NEWS);
        }
        return sendTemplateCardMsg(corpid, corpsecret, agentid, sendTo, model, duplicateCheckInterval);

    }

    public static Result sendTemplateCardNewsMsg(String sendTo, TemplateCardNewsModel model) {
        return sendTemplateCardNewsMsg(sendTo, model, null);

    }

    public static Result sendTemplateCardNewsMsg(String sendTo, TemplateCardNewsModel model, Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTemplateCardNewsMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, model,
                duplicateCheckInterval);

    }

    /**
     * 发送图文展示型通知模板
     * 
     * @Title sendTemplateCardNewsMsg
     * @author 吕凯
     * @date 2021年9月13日 下午3:03:45
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     * @param title
     * @param imagePath
     * @param url
     * @param duplicateCheckInterval
     * @return Result
     */
    public static Result sendTemplateCardNewsMsg(String corpid, String corpsecret, String agentid, String sendTo, String title,
            String imagePath, String url, Integer duplicateCheckInterval) {
        TemplateCardNewsModel model = TemplateCardNewsModel.builder().cardType(EweChatTool.TEMPL_CARD_TYPE_NEWS)
                .mainTitle(TmplCardMainTitleModel.builder().title(title).build())
                .cardImage(TmplCardImageModel.builder().url(imagePath).build())
                .cardAction(TmplCardActionModel.builder().type(1).url(url).build()).build();
        return sendMsg(corpid, corpsecret, agentid, parse2TemplateCardDataMap(agentid, sendTo, model, duplicateCheckInterval));

    }

    public static Result sendTemplateCardNewsMsg(String corpid, String corpsecret, String agentid, String sendTo, String title,
            String description, String url) {
        return sendTemplateCardNewsMsg(corpid, corpsecret, agentid, sendTo, title, description, url, null);

    }

    /**
     * 
     * 发送模板任务卡片消息
     * 
     * @Title sendTemplateCardNewsMsg
     * @author 吕凯
     * @date 2021年4月20日 下午6:04:09
     * @param sendTo
     * @param taskId
     * @param title
     * @param imagePath
     *            图片路径
     * @param url
     * @param btns
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Result
     */
    public static Result sendTemplateCardNewsMsg(String sendTo, String title, String imagePath, String url,
            Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTemplateCardNewsMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, title, imagePath, url,
                duplicateCheckInterval);
    }

    public static Result sendTemplateCardNewsMsg(String sendTo, String title, String imagePath, String url) {
        return sendTemplateCardNewsMsg(sendTo, title, imagePath, url, null);
    }

    // ========================================== 模板卡片：：按钮交互型 ====================================
    /**
     * 发送按钮交互型的通知
     * 
     * @Title sendTemplateCardTextMsg
     * @author 吕凯
     * @date 2021年9月13日 上午9:48:33
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     * @param model
     * @param duplicateCheckInterval
     * @return Result
     */

    public static Result sendTemplateCardButtonMsg(String corpid, String corpsecret, String agentid, String sendTo,
            TemplateCardButtonModel model, Integer duplicateCheckInterval) {
        return sendTemplateCardMsg(corpid, corpsecret, agentid, sendTo, model, duplicateCheckInterval);

    }

    public static Result sendTemplateCardButtonMsg(String sendTo, TemplateCardButtonModel model) {
        return sendTemplateCardButtonMsg(sendTo, model, null);

    }

    public static Result sendTemplateCardButtonMsg(String sendTo, TemplateCardButtonModel model, Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTemplateCardButtonMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, model,
                duplicateCheckInterval);

    }

    /**
     * 发送图文展示型通知模板
     * 
     * @Title sendTemplateCardNewsMsg
     * @author 吕凯
     * @date 2021年9月13日 下午3:03:45
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     * @param title
     * @param imagePath
     * @param url
     * @param duplicateCheckInterval
     * @return Result
     */
    public static Result sendTemplateCardButtonMsg(String corpid, String corpsecret, String agentid, String sendTo, String taskId,
            String title, String content, String url, String btnName, Integer duplicateCheckInterval) {
        TemplateCardButtonModel model = TemplateCardButtonModel.builder().cardType(EweChatTool.TEMPL_CARD_TYPE_BUTTON)
                .mainTitle(TmplCardMainTitleModel.builder().title(title).build()).taskId(taskId).subTitleText(content)
                .buttonList(ImmutableList.of(TmplCardBtn.builder().text(btnName).key("keyok").build()))
                .cardAction(TmplCardActionModel.builder().type(1).url(url).build()).build();
        return sendMsg(corpid, corpsecret, agentid, parse2TemplateCardDataMap(agentid, sendTo, model, duplicateCheckInterval));

    }

    public static Result sendTemplateCardButtonMsg(String corpid, String corpsecret, String agentid, String sendTo, String taskId,
            String title, String content, String url, String btnName) {
        return sendTemplateCardButtonMsg(corpid, corpsecret, agentid, sendTo, taskId, title, content, url, btnName, null);

    }

    /**
     * 
     * 发送模板卡片-按钮交互消息
     * 
     * @Title sendTemplateCardButtonMsg
     * @author 吕凯
     * @date 2021年4月20日 下午6:04:09
     * @param sendTo
     * @param taskId
     * @param title
     * @param imagePath
     *            图片路径
     * @param url
     * @param btns
     * @param duplicateCheckInterval
     *            重复信息检查时间间隔，单位秒，不检查设置为-1，默认600秒，最大4小时
     * @return Result
     */
    public static Result sendTemplateCardButtonMsg(String sendTo, String taskId, String title, String content, String url, String btnName,
            Integer duplicateCheckInterval) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return sendTemplateCardButtonMsg(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, taskId, title, content,
                url, btnName, duplicateCheckInterval);
    }

    public static Result sendTemplateCardButtonMsg(String sendTo, String taskId, String title, String content, String url, String btnName) {
        return sendTemplateCardButtonMsg(sendTo, taskId, title, content, url, btnName, null);
    }
    // ================================== 更新按钮文字 ===================================

    /**
     * 
     * 更新模板卡片（仅原卡片为 按钮交互型、投票选择型、多项选择型的卡片可以调用本接口更新）,可回调的卡片可以将按钮更新为不可点击状态，并且自定义文案
     * 
     * @Title updateTemplateCardButton
     * @author 吕凯
     * @date 2021年9月14日 上午9:02:04
     * @param corpid
     * @param corpsecret
     * @param agentid
     * @param sendTo
     *            发送给，多个用户用|分隔,全部用@all
     * @param responseCode
     *            响应码
     * @param replaceName
     *            替换按钮名称
     * @return Result
     */
    public static Result updateTemplateCardButton(String corpid, String corpsecret, String agentid, String sendTo, String responseCode,
            String replaceName) {
        Result result = getAccessToken(corpid, corpsecret, agentid);
        if (result.getSuccess()) { // 0是成功
            String accessToken = result.getMessage();
            String sendUrl = String.format(URL_UPDATE_TEMPLATE_CARD, accessToken);
            Map<String, Object> data = new HashMap<>();
            if ("@all".equals(sendTo)) {
                data.put("atall", 1); // 更新整个任务接收人员
            } else {
                data.put("userids", sendTo.split("\\|")); // 企业的成员ID列表（消息接收者，最多支持1000个）。
            }
            data.put(AGENTID, agentid); // 应用的agentid
            data.put("button", ImmutableMap.of("replace_name", replaceName)); // 设置替换文案
            data.put("response_code", responseCode); // 更新卡片所需要消费的code，可通过发消息接口和回调接口返回值获取，一个code只能调用一次该接口，且只能在24小时内调用

            EweChatLogModel.EweChatLogModelBuilder<?, ?> builder = EweChatLogModel.builder();
            builder.type(EweChatTool.APPLICATION).corpid(corpid).corpsecret(corpsecret).agentid(agentid).token(accessToken)
                    .msgType("updateTaskcard").sendTo(sendTo).data(data);

            JSONObject jsonResult = JsoupUtil.sendJson(data, sendUrl, EweChatTool.USER_AGENT, 10000);
            if (jsonResult != null) {

                EwechatResponse response = JSONObject.toJavaObject(jsonResult, EwechatResponse.class);
                result.setData(response);

//                Integer errcode = jsonResult.getInteger(EweChatTool.ERRCODE);
//                String errmsg = jsonResult.getString(EweChatTool.ERRMSG); // 信息
//                String invaliduser = jsonResult.getString(INVALID_USER); // 未发送成功的用户
//
//                String responseCodeResult = jsonResult.getString(RESPONSE_CODE); // 响应码
//                String msgId = jsonResult.getString(MSGID); // 响应码
                Integer errcode = response.getErrcode();
                String errmsg = response.getErrmsg(); // 信息
                String invaliduser = response.getInvaliduser(); // 未发送成功的用户
                String responseCodeResult = response.getResponseCode(); // 响应码
                String msgId = response.getMsgid(); // 响应码

                builder.errcode(errcode).errmsg(errmsg).responseCode(responseCodeResult).msgid(msgId).invaliduser(invaliduser);

                result.setMessage(errmsg);
                if (errcode == 0) { // 0是成功
                    result.setSuccess(true);
                    builder.success(EweChatTool.SUCCESS);
                } else {
                    result.setSuccess(false);
                    builder.success(EweChatTool.ERROR);
                }
                if (StringUtils.isNotEmpty(invaliduser)) {
                    result.setSuccess(false);
                    result.setMessage("发送失败的用户：" + invaliduser);
                }
                log.debug(jsonResult + "");
            }

            EweChatLogFactory.saveLog(builder.build()); // 调用保存日志的方法，没有实现需要具体项目自己实现
        }
        return result;

    }

    /**
     * 更新任务卡片状态
     * 
     * @Title updateTaskcard
     * @author 吕凯
     * @date 2021年4月21日 上午9:24:52
     * @param sendTo
     * @param taskId
     * @param replaceName
     * @return Result
     */
    public static Result updateTemplateCardButton(String sendTo, String taskId, String replaceName) {
        // 注意下面参数需要到企业微信中获取
        EweChatApplicationParams params = getConfig();
        return updateTemplateCardButton(params.getCorpId(), params.getCorpSecret(), params.getAgentId(), sendTo, taskId, replaceName);
    }
    // ========================== 替换模板卡片 =========================

}
